core: Split pull functionality into separate ostree-pull binary
authorColin Walters <walters@verbum.org>
Wed, 30 Nov 2011 14:21:14 +0000 (09:21 -0500)
committerColin Walters <walters@verbum.org>
Wed, 30 Nov 2011 14:21:14 +0000 (09:21 -0500)
This is to avoid everything depending on libsoup.

15 files changed:
Makefile-daemon.am
Makefile-libostree.am
Makefile-ostree.am
Makefile-otutil.am
configure.ac
src/ostbuild/ostbuild-add-artifacts [new file with mode: 0644]
src/ostbuild/ostbuild-chroot-compile-one [new file with mode: 0644]
src/ostbuild/ostbuild-chroot-compile-one-impl [new file with mode: 0644]
src/ostree/main.c
src/ostree/ostree-pull.c [new file with mode: 0644]
src/ostree/ot-builtin-pull.c [deleted file]
src/ostree/ot-builtins.h
src/ostree/ot-main.c [new file with mode: 0644]
src/ostree/ot-main.h [new file with mode: 0644]
tests/t0010-pull.sh

index c1d21e98423a3daa5024a9aa8c46cbcd7540a9f5..3b0a2b34d38a6ffc2c558b3d1bedd386aeffcb4d 100644 (file)
@@ -24,5 +24,5 @@ ostreed_SOURCES = src/daemon/ostreed.c \
        src/daemon/ot-daemon.c \
        $(NULL)
 
-ostreed_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/src/libotutil -I$(srcdir)/src/libostree -I$(srcdir)/src/daemon -DLOCALEDIR=\"$(datadir)/locale\" $(OT_COREBIN_DEP_CFLAGS)
-ostreed_LDADD = libotutil.la libostree.la $(OT_COREBIN_DEP_LIBS)
+ostreed_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/src/libotutil -I$(srcdir)/src/libostree -I$(srcdir)/src/daemon -DLOCALEDIR=\"$(datadir)/locale\" $(OT_DEP_GIO_UNIX_CFLAGS)
+ostreed_LDADD = libotutil.la libostree.la $(OT_DEP_GIO_UNIX_LIBS)
index bf53cc3b77d3c4562ee4acda31b869a4eb35326f..98a2504a38193ea8767c33e0a730822fb3cb3596 100644 (file)
@@ -31,5 +31,5 @@ libostree_la_SOURCES = src/libostree/ostree.h \
        src/libostree/ostree-checkout.c \
        src/libostree/ostree-checkout.h \
        $(NULL)
-libostree_la_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/src/libotutil -I$(srcdir)/src/libostree -DLOCALEDIR=\"$(datadir)/locale\" $(OT_COREBIN_DEP_CFLAGS)
-libostree_la_LIBADD = libotutil.la $(OT_COREBIN_DEP_LIBS)
+libostree_la_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/src/libotutil -I$(srcdir)/src/libostree -DLOCALEDIR=\"$(datadir)/locale\" $(OT_DEP_GIO_UNIX_CFLAGS)
+libostree_la_LIBADD = libotutil.la $(OT_DEP_GIO_UNIX_LIBS)
index 20c008251f6f42c5f7935daf0070e290994ba29f..eb84940dc4f0784a5b768fe94f787b596867f7d4 100644 (file)
@@ -35,10 +35,23 @@ ostree_SOURCES = src/ostree/main.c \
        src/ostree/ot-builtin-remote.c \
        src/ostree/ot-builtin-rev-parse.c \
        src/ostree/ot-builtin-show.c \
+       src/ostree/ot-main.h \
+       src/ostree/ot-main.c \
        $(NULL)
 
+ostree_bin_shared_cflags = $(AM_CFLAGS) -I$(srcdir)/src/libotutil -I$(srcdir)/src/libostree -I$(srcdir)/src/ostree  -DLOCALEDIR=\"$(datadir)/locale\"
+ostree_bin_shared_ldadd = libotutil.la libostree.la
+
+ostree_CFLAGS = $(ostree_bin_shared_cflags) $(OT_DEP_GIO_UNIX_CFLAGS)
+ostree_LDADD = $(ostree_bin_shared_ldadd) $(OT_DEP_GIO_UNIX_LIBS)
+
 if USE_LIBSOUP_GNOME
-ostree_SOURCES += src/ostree/ot-builtin-pull.c
+bin_PROGRAMS += ostree-pull
+ostree_pull_SOURCES = src/ostree/ot-main.h \
+       src/ostree/ot-main.c \
+       src/ostree/ostree-pull.c
+
+ostree_pull_CFLAGS = $(ostree_bin_shared_cflags) $(OT_DEP_SOUP_CFLAGS)
+ostree_pull_LDADD = $(ostree_bin_shared_ldadd) $(OT_DEP_SOUP_LIBS)
 endif
-ostree_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/src/libotutil -I$(srcdir)/src/libostree -I$(srcdir)/src/ostree  -DLOCALEDIR=\"$(datadir)/locale\" $(OT_COREBIN_DEP_CFLAGS)
-ostree_LDADD = libotutil.la libostree.la $(OT_COREBIN_DEP_LIBS)
+
index 6d4e492cf60516b59aeb51b2a798a02b0f5dae8e..dbe1763b6c31f151926db45bda3e3a62a513bab2 100644 (file)
@@ -32,5 +32,5 @@ libotutil_la_SOURCES = \
        src/libotutil/ot-glib-compat.h \
        src/libotutil/otutil.h \
        $(NULL)
-libotutil_la_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/src/libotutil -DLOCALEDIR=\"$(datadir)/locale\" $(GIO_UNIX_CFLAGS)
-libotutil_la_LIBADD = $(GIO_UNIX_LIBS)
+libotutil_la_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/src/libotutil -DLOCALEDIR=\"$(datadir)/locale\" $(OT_DEP_GIO_UNIX_CFLAGS)
+libotutil_la_LIBADD = $(OT_DEP_GIO_UNIX_LIBS)
index 839abea7c874d82846a89f07cf015333ea03f8a3..36a3cc3e6b34ce19362f52e9ce6b270fa95ead82 100644 (file)
@@ -25,23 +25,23 @@ LT_INIT([disable-static])
 PKG_PROG_PKG_CONFIG
 
 GIO_DEPENDENCY="gio-unix-2.0 >= 2.28"
-PKG_CHECK_MODULES(GIO_UNIX, [gio-unix-2.0 >= 2.28])
+SOUP_DEPENDENCY="libsoup-gnome-2.4 >= 2.34.0"
+
+PKG_CHECK_MODULES(OT_DEP_GIO_UNIX, $GIO_DEPENDENCY)
+
 AC_ARG_WITH(soup-gnome,
            AS_HELP_STRING([--without-soup-gnome], [Do not use libsoup-gnome (implies no pull support)]),
            :, with_soup_gnome=maybe)
 if test x$with_soup_gnome != xno; then
-    PKG_CHECK_MODULES(OT_COREBIN_DEP, [libsoup-gnome-2.4 >= 2.34.0 $GIO_DEPENDENCY], have_soup_gnome=yes, have_soup_gnome=no)
+    PKG_CHECK_EXISTS($SOUP_DEPENDENCY, have_soup_gnome=yes, have_soup_gnome=no)
     if test x$have_soup_gnome = xno && test x$with_soup_gnome != xmaybe; then
        AC_MSG_ERROR([libsoup-gnome is enabled but could not be found])
     fi
     if test x$have_soup_gnome = xyes; then
-        AC_DEFINE([HAVE_LIBSOUP_GNOME], [1], [Define if we have libsoup-gnome])
+       PKG_CHECK_MODULES(OT_DEP_SOUP, $SOUP_DEPENDENCY)
     else
-       PKG_CHECK_MODULES(OT_COREBIN_DEP, [$GIO_DEPENDENCY])
        with_soup_gnome=no
     fi         
-else
-    PKG_CHECK_MODULES(OT_COREBIN_DEP, [$GIO_DEPENDENCY])
 fi
 
 AM_CONDITIONAL(USE_LIBSOUP_GNOME, test $with_soup_gnome != no)
diff --git a/src/ostbuild/ostbuild-add-artifacts b/src/ostbuild/ostbuild-add-artifacts
new file mode 100644 (file)
index 0000000..f5069ec
--- /dev/null
@@ -0,0 +1,49 @@
+#!/usr/bin/python
+
+# Copyright (C) 2011 Colin Walters <walters@verbum.org>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+# ostbuild-compile-one-make wraps systems that implement the GNOME build API:
+# http://people.gnome.org/~walters/docs/build-api.txt
+
+import os,sys,subprocess,tempfile,re
+
+i=1
+repo=sys.argv[i]
+
+artifact_re = re.compile(r'^artifact-([^,]+)-([^,]+),(.+).tar.gz$')
+
+if os.getuid() != 0:
+    print "This program must be run as root."
+    sys.exit(1)
+
+def call_ostree_sync(*args):
+    subprocess.check_call(['ostree', '--repo=' + repo] + args)
+
+for arg in sys.argv[1:]:
+    match = artifact_re.match(arg)
+    if match is None
+        print "Invalid artifact name: %s" % (arg, )
+        sys.exit(1)
+    arch = match.group(1)
+    name = match.group(2)
+    version = match.group(3)
+    
+    branch_name = 'artifact-%s-%s' % (arch, name)
+
+    call_ostree_sync('commit', '-b', branch_name, '-s', version, 
+                     
diff --git a/src/ostbuild/ostbuild-chroot-compile-one b/src/ostbuild/ostbuild-chroot-compile-one
new file mode 100644 (file)
index 0000000..2d9a8a8
--- /dev/null
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# Copyright (C) 2011 Colin Walters <walters@verbum.org>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+#
+# Author: Colin Walters <walters@verbum.org>
+
+
+bn=$(basename $(pwd))
+ostbuild-nice-and-log-output "compile-${bn}.log" ostbuild-chroot-compile-one-impl "$@"
diff --git a/src/ostbuild/ostbuild-chroot-compile-one-impl b/src/ostbuild/ostbuild-chroot-compile-one-impl
new file mode 100644 (file)
index 0000000..9c253ea
--- /dev/null
@@ -0,0 +1,53 @@
+#!/usr/bin/python
+
+# Copyright (C) 2011 Colin Walters <walters@verbum.org>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+import os,sys,re,subprocess
+
+i=1
+repo=sys.argv[i]
+i += 1
+chroot_path=sys.argv[i]
+i += 1
+args=sys.argv[i:]
+
+if os.getuid() != 0:
+    print "This program must be run as root."
+    sys.exit(1)
+
+rootdir=os.path.join(chroot_path, 'root')
+
+if not os.path.isdir(rootdir):
+    print "Not a directory: %s" % (rootdir, )
+    sys.exit(1)
+
+builddir = os.path.join(rootdir, 'ostree-build')
+if not os.path.isdir(builddir):
+    os.mkdir(builddir)
+
+
+def run_in_chroot(args):
+    proc_path=os.path.join(chroot_path, 'proc')
+    subprocess.check_call(['mount', '-t', 'proc', 'proc', proc_path])
+
+    try:
+        subprocess.check_call(['chroot', chroot_path])
+    finally:
+        subprocess.call(['umount', proc_path])
+
+run_in_chroot(args)
index 5aea6c0abb295d1a324eaf6db6ba0c8ce2550210..301a512dfe10e1c7c8d414a1ac6ea9c8f69400e7 100644 (file)
@@ -26,6 +26,7 @@
 
 #include <string.h>
 
+#include "ot-main.h"
 #include "ot-builtins.h"
 
 static OstreeBuiltin builtins[] = {
@@ -38,9 +39,6 @@ static OstreeBuiltin builtins[] = {
   { "local-clone", ostree_builtin_local_clone, 0 },
   { "log", ostree_builtin_log, 0 },
   { "ls", ostree_builtin_ls, 0 },
-#ifdef HAVE_LIBSOUP_GNOME
-  { "pull", ostree_builtin_pull, 0 },
-#endif
   { "fsck", ostree_builtin_fsck, 0 },
   { "remote", ostree_builtin_remote, 0 },
   { "rev-parse", ostree_builtin_rev_parse, 0 },
@@ -50,126 +48,9 @@ static OstreeBuiltin builtins[] = {
   { NULL }
 };
 
-static int
-usage (char **argv, gboolean is_error)
-{
-  OstreeBuiltin *builtin = builtins;
-  void (*print_func) (const gchar *format, ...);
-
-  if (is_error)
-    print_func = g_printerr;
-  else
-    print_func = g_print;
-
-  print_func ("usage: %s --repo=PATH COMMAND [options]\n",
-              argv[0]);
-  print_func ("Builtin commands:\n");
-
-  while (builtin->name)
-    {
-      print_func ("  %s\n", builtin->name);
-      builtin++;
-    }
-  return (is_error ? 1 : 0);
-}
-
-static void
-prep_builtin_argv (const char *builtin,
-                   int argc,
-                   char **argv,
-                   int *out_argc,
-                   char ***out_argv)
-{
-  int i;
-  char **cmd_argv;
-  
-  cmd_argv = g_new0 (char *, argc + 2);
-  
-  cmd_argv[0] = (char*)builtin;
-  for (i = 0; i < argc; i++)
-    cmd_argv[i+1] = argv[i];
-  cmd_argv[i+1] = NULL;
-  *out_argc = argc+1;
-  *out_argv = cmd_argv;
-}
-
-static void
-set_error_print_usage (GError **error, const char *msg, char **argv)
-{
-  g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, msg);
-  usage (argv, TRUE);
-}
-
 int
 main (int    argc,
       char **argv)
 {
-  OstreeBuiltin *builtin;
-  GError *error = NULL;
-  int cmd_argc;
-  char **cmd_argv = NULL;
-  gboolean am_root;
-  gboolean have_repo_arg;
-  const char *cmd = NULL;
-  const char *repo = NULL;
-
-  g_type_init ();
-
-  g_set_prgname (argv[0]);
-
-  if (argc < 2)
-    return usage (argv, 1);
-
-  am_root = getuid () == 0;
-  have_repo_arg = g_str_has_prefix (argv[1], "--repo=");
-
-  if (!have_repo_arg && am_root)
-    repo = "/sysroot/ostree/repo";
-  else if (have_repo_arg)
-    repo = argv[1] + strlen ("--repo=");
-  else
-    repo = NULL;
-
-  if (!have_repo_arg)
-    cmd = argv[1];
-  else
-    cmd = argv[2];
-
-  builtin = builtins;
-  while (builtin->name)
-    {
-      if (strcmp (cmd, builtin->name) == 0)
-        break;
-      builtin++;
-    }
-
-  if (!builtin)
-    {
-      set_error_print_usage (&error, "Unknown command", argv);
-      goto out;
-    }
-
-  if (repo == NULL && !(builtin->flags & OSTREE_BUILTIN_FLAG_NO_REPO))
-    {
-      set_error_print_usage (&error, "Command requires a --repo argument", argv);
-      goto out;
-    }
-  
-  if (!have_repo_arg)
-    prep_builtin_argv (cmd, argc-2, argv+2, &cmd_argc, &cmd_argv);
-  else
-    prep_builtin_argv (cmd, argc-3, argv+3, &cmd_argc, &cmd_argv);
-
-  if (!builtin->fn (cmd_argc, cmd_argv, repo, &error))
-    goto out;
-
- out:
-  g_free (cmd_argv);
-  if (error)
-    {
-      g_printerr ("%s\n", error->message);
-      g_clear_error (&error);
-      return 1;
-    }
-  return 0;
+  return ostree_main (argc, argv, builtins);
 }
diff --git a/src/ostree/ostree-pull.c b/src/ostree/ostree-pull.c
new file mode 100644 (file)
index 0000000..3c9cecf
--- /dev/null
@@ -0,0 +1,405 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2011 Colin Walters <walters@verbum.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Colin Walters <walters@verbum.org>
+ */
+
+#include "config.h"
+
+#include <libsoup/soup-gnome.h>
+
+#include "ostree.h"
+#include "ot-main.h"
+
+gboolean verbose;
+
+static GOptionEntry options[] = {
+  { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Show more information", NULL },
+};
+
+static void
+log_verbose (const char  *fmt,
+             ...) G_GNUC_PRINTF (1, 2);
+
+static void
+log_verbose (const char  *fmt,
+             ...)
+{
+  va_list args;
+  char *msg;
+
+  if (!verbose)
+    return;
+
+  va_start (args, fmt);
+  
+  msg = g_strdup_vprintf (fmt, args);
+  g_print ("%s\n", msg);
+  g_free (msg);
+}
+
+static gboolean
+fetch_uri (OstreeRepo  *repo,
+           SoupSession *soup,
+           SoupURI     *uri,
+           char       **temp_filename,
+           GError     **error)
+{
+  gboolean ret = FALSE;
+  SoupMessage *msg = NULL;
+  guint response;
+  char *template = NULL;
+  int fd;
+  SoupBuffer *buf = NULL;
+  GFile *tempf = NULL;
+  char *uri_string = NULL;
+  
+  uri_string = soup_uri_to_string (uri, FALSE);
+  log_verbose ("Fetching %s", uri_string);
+  msg = soup_message_new_from_uri (SOUP_METHOD_GET, uri);
+  
+  response = soup_session_send_message (soup, msg);
+  if (response != 200)
+    {
+      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                   "Failed to retrieve '%s': %d %s",
+                   uri_string, response, msg->reason_phrase);
+      goto out;
+    }
+
+  template = g_strdup_printf ("%s/tmp-fetchXXXXXX", ostree_repo_get_path (repo));
+  
+  fd = g_mkstemp (template);
+  if (fd < 0)
+    {
+      ot_util_set_error_from_errno (error, errno);
+      goto out;
+    }
+  close (fd);
+  tempf = ot_gfile_new_for_path (template);
+
+  buf = soup_message_body_flatten (msg->response_body);
+
+  if (!g_file_replace_contents (tempf, buf->data, buf->length, NULL, FALSE, 0, NULL, NULL, error))
+    goto out;
+  
+  *temp_filename = template;
+  template = NULL;
+
+  ret = TRUE;
+ out:
+  g_free (uri_string);
+  g_free (template);
+  g_clear_object (&msg);
+  g_clear_object (&tempf);
+  return ret;
+}
+
+static gboolean
+store_object (OstreeRepo  *repo,
+              SoupSession *soup,
+              SoupURI     *baseuri,
+              const char  *object,
+              OstreeObjectType objtype,
+              gboolean    *did_exist,
+              GError     **error)
+{
+  gboolean ret = FALSE;
+  char *filename = NULL;
+  char *objpath = NULL;
+  char *relpath = NULL;
+  SoupURI *obj_uri = NULL;
+
+  objpath = ostree_get_relative_object_path (object, objtype, TRUE);
+  obj_uri = soup_uri_copy (baseuri);
+  relpath = g_build_filename (soup_uri_get_path (obj_uri), objpath, NULL);
+  soup_uri_set_path (obj_uri, relpath);
+
+  if (!fetch_uri (repo, soup, obj_uri, &filename, error))
+    goto out;
+
+  if (!ostree_repo_store_packfile (repo, object, filename, objtype, did_exist, error))
+    goto out;
+
+  ret = TRUE;
+ out:
+  if (obj_uri)
+    soup_uri_free (obj_uri);
+  if (filename)
+    (void) unlink (filename);
+  g_free (filename);
+  g_free (objpath);
+  g_free (relpath);
+  return ret;
+}
+
+static gboolean
+store_tree_recurse (OstreeRepo   *repo,
+                    SoupSession  *soup,
+                    SoupURI      *base_uri,
+                    const char   *rev,
+                    GError      **error)
+{
+  gboolean ret = FALSE;
+  GVariant *tree = NULL;
+  GVariant *files_variant = NULL;
+  GVariant *dirs_variant = NULL;
+  OstreeSerializedVariantType metatype;
+  gboolean did_exist;
+  int i, n;
+
+  if (!store_object (repo, soup, base_uri, rev, OSTREE_OBJECT_TYPE_META, &did_exist, error))
+    goto out;
+
+  if (did_exist)
+    log_verbose ("Already have tree %s", rev);
+  else
+    {
+      if (!ostree_repo_load_variant (repo, rev, &metatype, &tree, error))
+        goto out;
+      
+      if (metatype != OSTREE_SERIALIZED_TREE_VARIANT)
+        {
+          g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                       "Tree metadata '%s' has wrong type %d, expected %d",
+                       rev, metatype, OSTREE_SERIALIZED_TREE_VARIANT);
+          goto out;
+        }
+      
+      /* PARSE OSTREE_SERIALIZED_TREE_VARIANT */
+      files_variant = g_variant_get_child_value (tree, 2);
+      dirs_variant = g_variant_get_child_value (tree, 3);
+      
+      n = g_variant_n_children (files_variant);
+      for (i = 0; i < n; i++)
+        {
+          const char *filename;
+          const char *checksum;
+
+          g_variant_get_child (files_variant, i, "(&s&s)", &filename, &checksum);
+
+          if (!store_object (repo, soup, base_uri, checksum, OSTREE_OBJECT_TYPE_FILE, &did_exist, error))
+            goto out;
+        }
+      
+      n = g_variant_n_children (dirs_variant);
+      for (i = 0; i < n; i++)
+        {
+          const char *dirname;
+          const char *tree_checksum;
+          const char *meta_checksum;
+
+          g_variant_get_child (dirs_variant, i, "(&s&s&s)",
+                               &dirname, &tree_checksum, &meta_checksum);
+
+          if (!store_object (repo, soup, base_uri, meta_checksum, OSTREE_OBJECT_TYPE_META, &did_exist, error))
+            goto out;
+
+          if (!store_tree_recurse (repo, soup, base_uri, tree_checksum, error))
+            goto out;
+        }
+    }
+
+  ret = TRUE;
+ out:
+  ot_clear_gvariant (&tree);
+  ot_clear_gvariant (&files_variant);
+  ot_clear_gvariant (&dirs_variant);
+  return ret;
+}
+
+static gboolean
+store_commit_recurse (OstreeRepo   *repo,
+                      SoupSession  *soup,
+                      SoupURI      *base_uri,
+                      const char   *rev,
+                      GError      **error)
+{
+  gboolean ret = FALSE;
+  GVariant *commit = NULL;
+  OstreeSerializedVariantType metatype;
+  const char *tree_contents_checksum;
+  const char *tree_meta_checksum;
+  gboolean did_exist;
+
+  if (!store_object (repo, soup, base_uri, rev, OSTREE_OBJECT_TYPE_META, &did_exist, error))
+    goto out;
+
+  if (did_exist)
+    log_verbose ("Already have commit %s", rev);
+  else
+    {
+      if (!ostree_repo_load_variant (repo, rev, &metatype, &commit, error))
+        goto out;
+      
+      if (metatype != OSTREE_SERIALIZED_COMMIT_VARIANT)
+        {
+          g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                       "Commit '%s' has wrong type %d, expected %d",
+                       rev, metatype, OSTREE_SERIALIZED_COMMIT_VARIANT);
+          goto out;
+        }
+      
+      /* PARSE OSTREE_SERIALIZED_COMMIT_VARIANT */
+      g_variant_get_child (commit, 6, "&s", &tree_contents_checksum);
+      g_variant_get_child (commit, 7, "&s", &tree_meta_checksum);
+      
+      if (!store_object (repo, soup, base_uri, tree_meta_checksum, OSTREE_OBJECT_TYPE_META, &did_exist, error))
+        goto out;
+      
+      if (!store_tree_recurse (repo, soup, base_uri, tree_contents_checksum, error))
+        goto out;
+    }
+
+  ret = TRUE;
+ out:
+  ot_clear_gvariant (&commit);
+  return ret;
+}
+                      
+static gboolean
+ostree_builtin_pull (int argc, char **argv, const char *repo_path, GError **error)
+{
+  GOptionContext *context;
+  gboolean ret = FALSE;
+  OstreeRepo *repo = NULL;
+  const char *remote;
+  const char *branch;
+  char *remote_branch_ref_path = NULL;
+  char *key = NULL;
+  char *baseurl = NULL;
+  char *refpath = NULL;
+  char *temppath = NULL;
+  GFile *tempf = NULL;
+  char *remote_ref = NULL;
+  char *original_rev = NULL;
+  GKeyFile *config = NULL;
+  SoupURI *base_uri = NULL;
+  SoupURI *target_uri = NULL;
+  SoupSession *soup = NULL;
+  char *rev = NULL;
+
+  context = g_option_context_new ("REMOTE BRANCH - Download data from remote repository");
+  g_option_context_add_main_entries (context, options, NULL);
+
+  if (!g_option_context_parse (context, &argc, &argv, error))
+    goto out;
+
+  repo = ostree_repo_new (repo_path);
+  if (!ostree_repo_check (repo, error))
+    goto out;
+
+  if (argc < 3)
+    {
+      ot_util_usage_error (context, "REMOTE and BRANCH must be specified", error);
+      goto out;
+    }
+
+  remote = argv[1];
+  branch = argv[2];
+
+  remote_ref = g_strdup_printf ("%s/%s", remote, branch);
+
+  if (!ostree_repo_resolve_rev (repo, remote_ref, TRUE, &original_rev, error))
+    goto out;
+
+  config = ostree_repo_get_config (repo);
+
+  key = g_strdup_printf ("remote \"%s\"", remote);
+  baseurl = g_key_file_get_string (config, key, "url", error);
+  if (!baseurl)
+    goto out;
+  base_uri = soup_uri_new (baseurl);
+  if (!base_uri)
+    {
+      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                   "Failed to parse url '%s'", baseurl);
+      goto out;
+    }
+  target_uri = soup_uri_copy (base_uri);
+  g_free (refpath);
+  refpath = g_build_filename (soup_uri_get_path (target_uri), "refs", "heads", branch, NULL);
+  soup_uri_set_path (target_uri, refpath);
+  
+  soup = soup_session_sync_new_with_options (SOUP_SESSION_USER_AGENT, "ostree ",
+                                             SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_GNOME_FEATURES_2_26,
+                                             SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_CONTENT_DECODER,
+                                             SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_COOKIE_JAR,
+                                             NULL);
+  if (!fetch_uri (repo, soup, target_uri, &temppath, error))
+    goto out;
+  tempf = ot_gfile_new_for_path (temppath);
+
+  if (!ot_gfile_load_contents_utf8 (tempf, &rev, NULL, NULL, error))
+    goto out;
+  g_strchomp (rev);
+
+  if (original_rev && strcmp (rev, original_rev) == 0)
+    {
+      g_print ("No changes in %s\n", remote_ref);
+    }
+  else
+    {
+      if (!ostree_validate_checksum_string (rev, error))
+        goto out;
+      
+      if (!store_commit_recurse (repo, soup, base_uri, rev, error))
+        goto out;
+      
+      if (!ostree_repo_write_ref (repo, remote, branch, rev, error))
+        goto out;
+      
+      g_print ("remote %s is now %s\n", remote_ref, rev);
+    }
+  ret = TRUE;
+ out:
+  if (context)
+    g_option_context_free (context);
+  if (temppath)
+    (void) unlink (temppath);
+  g_free (temppath);
+  g_free (key);
+  g_free (rev);
+  g_free (remote_ref);
+  g_free (original_rev);
+  g_free (baseurl);
+  g_free (refpath);
+  g_free (remote_branch_ref_path);
+  g_clear_object (&soup);
+  if (base_uri)
+    soup_uri_free (base_uri);
+  if (target_uri)
+    soup_uri_free (target_uri);
+  g_clear_object (&repo);
+  g_clear_object (&soup);
+  return ret;
+}
+
+static OstreeBuiltin builtins[] = {
+  { "pull", ostree_builtin_pull, 0 },
+  { NULL }
+};
+
+int
+main (int    argc,
+      char **argv)
+{
+  return ostree_main (argc, argv, builtins);
+}
diff --git a/src/ostree/ot-builtin-pull.c b/src/ostree/ot-builtin-pull.c
deleted file mode 100644 (file)
index 012c094..0000000
+++ /dev/null
@@ -1,395 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
- *
- * Copyright (C) 2011 Colin Walters <walters@verbum.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Author: Colin Walters <walters@verbum.org>
- */
-
-#include "config.h"
-
-#include "ot-builtins.h"
-#include "ostree.h"
-
-#include <glib/gi18n.h>
-
-#include <libsoup/soup-gnome.h>
-
-gboolean verbose;
-
-static GOptionEntry options[] = {
-  { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Show more information", NULL },
-};
-
-static void
-log_verbose (const char  *fmt,
-             ...) G_GNUC_PRINTF (1, 2);
-
-static void
-log_verbose (const char  *fmt,
-             ...)
-{
-  va_list args;
-  char *msg;
-
-  if (!verbose)
-    return;
-
-  va_start (args, fmt);
-  
-  msg = g_strdup_vprintf (fmt, args);
-  g_print ("%s\n", msg);
-  g_free (msg);
-}
-
-static gboolean
-fetch_uri (OstreeRepo  *repo,
-           SoupSession *soup,
-           SoupURI     *uri,
-           char       **temp_filename,
-           GError     **error)
-{
-  gboolean ret = FALSE;
-  SoupMessage *msg = NULL;
-  guint response;
-  char *template = NULL;
-  int fd;
-  SoupBuffer *buf = NULL;
-  GFile *tempf = NULL;
-  char *uri_string = NULL;
-  
-  uri_string = soup_uri_to_string (uri, FALSE);
-  log_verbose ("Fetching %s", uri_string);
-  msg = soup_message_new_from_uri (SOUP_METHOD_GET, uri);
-  
-  response = soup_session_send_message (soup, msg);
-  if (response != 200)
-    {
-      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-                   "Failed to retrieve '%s': %d %s",
-                   uri_string, response, msg->reason_phrase);
-      goto out;
-    }
-
-  template = g_strdup_printf ("%s/tmp-fetchXXXXXX", ostree_repo_get_path (repo));
-  
-  fd = g_mkstemp (template);
-  if (fd < 0)
-    {
-      ot_util_set_error_from_errno (error, errno);
-      goto out;
-    }
-  close (fd);
-  tempf = ot_gfile_new_for_path (template);
-
-  buf = soup_message_body_flatten (msg->response_body);
-
-  if (!g_file_replace_contents (tempf, buf->data, buf->length, NULL, FALSE, 0, NULL, NULL, error))
-    goto out;
-  
-  *temp_filename = template;
-  template = NULL;
-
-  ret = TRUE;
- out:
-  g_free (uri_string);
-  g_free (template);
-  g_clear_object (&msg);
-  g_clear_object (&tempf);
-  return ret;
-}
-
-static gboolean
-store_object (OstreeRepo  *repo,
-              SoupSession *soup,
-              SoupURI     *baseuri,
-              const char  *object,
-              OstreeObjectType objtype,
-              gboolean    *did_exist,
-              GError     **error)
-{
-  gboolean ret = FALSE;
-  char *filename = NULL;
-  char *objpath = NULL;
-  char *relpath = NULL;
-  SoupURI *obj_uri = NULL;
-
-  objpath = ostree_get_relative_object_path (object, objtype, TRUE);
-  obj_uri = soup_uri_copy (baseuri);
-  relpath = g_build_filename (soup_uri_get_path (obj_uri), objpath, NULL);
-  soup_uri_set_path (obj_uri, relpath);
-
-  if (!fetch_uri (repo, soup, obj_uri, &filename, error))
-    goto out;
-
-  if (!ostree_repo_store_packfile (repo, object, filename, objtype, did_exist, error))
-    goto out;
-
-  ret = TRUE;
- out:
-  if (obj_uri)
-    soup_uri_free (obj_uri);
-  if (filename)
-    (void) unlink (filename);
-  g_free (filename);
-  g_free (objpath);
-  g_free (relpath);
-  return ret;
-}
-
-static gboolean
-store_tree_recurse (OstreeRepo   *repo,
-                    SoupSession  *soup,
-                    SoupURI      *base_uri,
-                    const char   *rev,
-                    GError      **error)
-{
-  gboolean ret = FALSE;
-  GVariant *tree = NULL;
-  GVariant *files_variant = NULL;
-  GVariant *dirs_variant = NULL;
-  OstreeSerializedVariantType metatype;
-  gboolean did_exist;
-  int i, n;
-
-  if (!store_object (repo, soup, base_uri, rev, OSTREE_OBJECT_TYPE_META, &did_exist, error))
-    goto out;
-
-  if (did_exist)
-    log_verbose ("Already have tree %s", rev);
-  else
-    {
-      if (!ostree_repo_load_variant (repo, rev, &metatype, &tree, error))
-        goto out;
-      
-      if (metatype != OSTREE_SERIALIZED_TREE_VARIANT)
-        {
-          g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-                       "Tree metadata '%s' has wrong type %d, expected %d",
-                       rev, metatype, OSTREE_SERIALIZED_TREE_VARIANT);
-          goto out;
-        }
-      
-      /* PARSE OSTREE_SERIALIZED_TREE_VARIANT */
-      files_variant = g_variant_get_child_value (tree, 2);
-      dirs_variant = g_variant_get_child_value (tree, 3);
-      
-      n = g_variant_n_children (files_variant);
-      for (i = 0; i < n; i++)
-        {
-          const char *filename;
-          const char *checksum;
-
-          g_variant_get_child (files_variant, i, "(&s&s)", &filename, &checksum);
-
-          if (!store_object (repo, soup, base_uri, checksum, OSTREE_OBJECT_TYPE_FILE, &did_exist, error))
-            goto out;
-        }
-      
-      n = g_variant_n_children (dirs_variant);
-      for (i = 0; i < n; i++)
-        {
-          const char *dirname;
-          const char *tree_checksum;
-          const char *meta_checksum;
-
-          g_variant_get_child (dirs_variant, i, "(&s&s&s)",
-                               &dirname, &tree_checksum, &meta_checksum);
-
-          if (!store_object (repo, soup, base_uri, meta_checksum, OSTREE_OBJECT_TYPE_META, &did_exist, error))
-            goto out;
-
-          if (!store_tree_recurse (repo, soup, base_uri, tree_checksum, error))
-            goto out;
-        }
-    }
-
-  ret = TRUE;
- out:
-  ot_clear_gvariant (&tree);
-  ot_clear_gvariant (&files_variant);
-  ot_clear_gvariant (&dirs_variant);
-  return ret;
-}
-
-static gboolean
-store_commit_recurse (OstreeRepo   *repo,
-                      SoupSession  *soup,
-                      SoupURI      *base_uri,
-                      const char   *rev,
-                      GError      **error)
-{
-  gboolean ret = FALSE;
-  GVariant *commit = NULL;
-  OstreeSerializedVariantType metatype;
-  const char *tree_contents_checksum;
-  const char *tree_meta_checksum;
-  gboolean did_exist;
-
-  if (!store_object (repo, soup, base_uri, rev, OSTREE_OBJECT_TYPE_META, &did_exist, error))
-    goto out;
-
-  if (did_exist)
-    log_verbose ("Already have commit %s", rev);
-  else
-    {
-      if (!ostree_repo_load_variant (repo, rev, &metatype, &commit, error))
-        goto out;
-      
-      if (metatype != OSTREE_SERIALIZED_COMMIT_VARIANT)
-        {
-          g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-                       "Commit '%s' has wrong type %d, expected %d",
-                       rev, metatype, OSTREE_SERIALIZED_COMMIT_VARIANT);
-          goto out;
-        }
-      
-      /* PARSE OSTREE_SERIALIZED_COMMIT_VARIANT */
-      g_variant_get_child (commit, 6, "&s", &tree_contents_checksum);
-      g_variant_get_child (commit, 7, "&s", &tree_meta_checksum);
-      
-      if (!store_object (repo, soup, base_uri, tree_meta_checksum, OSTREE_OBJECT_TYPE_META, &did_exist, error))
-        goto out;
-      
-      if (!store_tree_recurse (repo, soup, base_uri, tree_contents_checksum, error))
-        goto out;
-    }
-
-  ret = TRUE;
- out:
-  ot_clear_gvariant (&commit);
-  return ret;
-}
-                      
-gboolean
-ostree_builtin_pull (int argc, char **argv, const char *repo_path, GError **error)
-{
-  GOptionContext *context;
-  gboolean ret = FALSE;
-  OstreeRepo *repo = NULL;
-  const char *remote;
-  const char *branch;
-  char *remote_branch_ref_path = NULL;
-  char *key = NULL;
-  char *baseurl = NULL;
-  char *refpath = NULL;
-  char *temppath = NULL;
-  GFile *tempf = NULL;
-  char *remote_ref = NULL;
-  char *original_rev = NULL;
-  GKeyFile *config = NULL;
-  SoupURI *base_uri = NULL;
-  SoupURI *target_uri = NULL;
-  SoupSession *soup = NULL;
-  char *rev = NULL;
-
-  context = g_option_context_new ("REMOTE BRANCH - Download data from remote repository");
-  g_option_context_add_main_entries (context, options, NULL);
-
-  if (!g_option_context_parse (context, &argc, &argv, error))
-    goto out;
-
-  repo = ostree_repo_new (repo_path);
-  if (!ostree_repo_check (repo, error))
-    goto out;
-
-  if (argc < 3)
-    {
-      ot_util_usage_error (context, "REMOTE and BRANCH must be specified", error);
-      goto out;
-    }
-
-  remote = argv[1];
-  branch = argv[2];
-
-  remote_ref = g_strdup_printf ("%s/%s", remote, branch);
-
-  if (!ostree_repo_resolve_rev (repo, remote_ref, TRUE, &original_rev, error))
-    goto out;
-
-  config = ostree_repo_get_config (repo);
-
-  key = g_strdup_printf ("remote \"%s\"", remote);
-  baseurl = g_key_file_get_string (config, key, "url", error);
-  if (!baseurl)
-    goto out;
-  base_uri = soup_uri_new (baseurl);
-  if (!base_uri)
-    {
-      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-                   "Failed to parse url '%s'", baseurl);
-      goto out;
-    }
-  target_uri = soup_uri_copy (base_uri);
-  g_free (refpath);
-  refpath = g_build_filename (soup_uri_get_path (target_uri), "refs", "heads", branch, NULL);
-  soup_uri_set_path (target_uri, refpath);
-  
-  soup = soup_session_sync_new_with_options (SOUP_SESSION_USER_AGENT, "ostree ",
-                                             SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_GNOME_FEATURES_2_26,
-                                             SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_CONTENT_DECODER,
-                                             SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_COOKIE_JAR,
-                                             NULL);
-  if (!fetch_uri (repo, soup, target_uri, &temppath, error))
-    goto out;
-  tempf = ot_gfile_new_for_path (temppath);
-
-  if (!ot_gfile_load_contents_utf8 (tempf, &rev, NULL, NULL, error))
-    goto out;
-  g_strchomp (rev);
-
-  if (original_rev && strcmp (rev, original_rev) == 0)
-    {
-      g_print ("No changes in %s\n", remote_ref);
-    }
-  else
-    {
-      if (!ostree_validate_checksum_string (rev, error))
-        goto out;
-      
-      if (!store_commit_recurse (repo, soup, base_uri, rev, error))
-        goto out;
-      
-      if (!ostree_repo_write_ref (repo, remote, branch, rev, error))
-        goto out;
-      
-      g_print ("remote %s is now %s\n", remote_ref, rev);
-    }
-  ret = TRUE;
- out:
-  if (context)
-    g_option_context_free (context);
-  if (temppath)
-    (void) unlink (temppath);
-  g_free (temppath);
-  g_free (key);
-  g_free (rev);
-  g_free (remote_ref);
-  g_free (original_rev);
-  g_free (baseurl);
-  g_free (refpath);
-  g_free (remote_branch_ref_path);
-  g_clear_object (&soup);
-  if (base_uri)
-    soup_uri_free (base_uri);
-  if (target_uri)
-    soup_uri_free (target_uri);
-  g_clear_object (&repo);
-  g_clear_object (&soup);
-  return ret;
-}
index afef91f88ceb2a73aa930149fa34900e5da239db..cfacaad155bc316cd4a0ea68bb0dc83cfdb9ae71 100644 (file)
 
 G_BEGIN_DECLS
 
-typedef enum {
-  OSTREE_BUILTIN_FLAG_NONE = 0,
-  OSTREE_BUILTIN_FLAG_NO_REPO = 1,
-} OstreeBuiltinFlags;
-
-typedef struct {
-  const char *name;
-  gboolean (*fn) (int argc, char **argv, const char *repo, GError **error);
-  int flags; /* OstreeBuiltinFlags */
-} OstreeBuiltin;
-
 gboolean ostree_builtin_checkout (int argc, char **argv, const char *repo, GError **error);
 gboolean ostree_builtin_checksum (int argc, char **argv, const char *repo, GError **error);
 gboolean ostree_builtin_commit (int argc, char **argv, const char *repo, GError **error);
@@ -47,7 +36,6 @@ gboolean ostree_builtin_init (int argc, char **argv, const char *repo, GError **
 gboolean ostree_builtin_local_clone (int argc, char **argv, const char *repo, GError **error);
 gboolean ostree_builtin_log (int argc, char **argv, const char *repo, GError **error);
 gboolean ostree_builtin_ls (int argc, char **argv, const char *repo, GError **error);
-gboolean ostree_builtin_pull (int argc, char **argv, const char *repo, GError **error);
 gboolean ostree_builtin_run_triggers (int argc, char **argv, const char *repo, GError **error);
 gboolean ostree_builtin_fsck (int argc, char **argv, const char *repo, GError **error);
 gboolean ostree_builtin_show (int argc, char **argv, const char *repo, GError **error);
diff --git a/src/ostree/ot-main.c b/src/ostree/ot-main.c
new file mode 100644 (file)
index 0000000..e951252
--- /dev/null
@@ -0,0 +1,166 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2011 Colin Walters <walters@verbum.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Colin Walters <walters@verbum.org>
+ */
+
+#include "config.h"
+
+#include <gio/gio.h>
+
+#include <string.h>
+
+#include "ot-main.h"
+
+static int
+usage (char **argv, OstreeBuiltin *builtins, gboolean is_error)
+{
+  OstreeBuiltin *builtin = builtins;
+  void (*print_func) (const gchar *format, ...);
+
+  if (is_error)
+    print_func = g_printerr;
+  else
+    print_func = g_print;
+
+  print_func ("usage: %s --repo=PATH COMMAND [options]\n",
+              argv[0]);
+  print_func ("Builtin commands:\n");
+
+  while (builtin->name)
+    {
+      print_func ("  %s\n", builtin->name);
+      builtin++;
+    }
+  return (is_error ? 1 : 0);
+}
+
+static void
+prep_builtin_argv (const char *builtin,
+                   int argc,
+                   char **argv,
+                   int *out_argc,
+                   char ***out_argv)
+{
+  int i;
+  char **cmd_argv;
+  
+  cmd_argv = g_new0 (char *, argc + 2);
+  
+  cmd_argv[0] = (char*)builtin;
+  for (i = 0; i < argc; i++)
+    cmd_argv[i+1] = argv[i];
+  cmd_argv[i+1] = NULL;
+  *out_argc = argc+1;
+  *out_argv = cmd_argv;
+}
+
+static void
+set_error_print_usage (GError **error, OstreeBuiltin *builtins, const char *msg, char **argv)
+{
+  g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, msg);
+  usage (argv, builtins, TRUE);
+}
+
+int
+ostree_main (int    argc,
+             char **argv,
+             OstreeBuiltin  *builtins)
+{
+  OstreeBuiltin *builtin;
+  GError *error = NULL;
+  int cmd_argc;
+  char **cmd_argv = NULL;
+  gboolean am_root;
+  gboolean have_repo_arg;
+  const char *cmd = NULL;
+  const char *repo = NULL;
+  int arg_off;
+
+  g_type_init ();
+
+  g_set_prgname (argv[0]);
+
+  if (argc < 2)
+    return usage (argv, builtins, 1);
+
+  am_root = getuid () == 0;
+  have_repo_arg = g_str_has_prefix (argv[1], "--repo=");
+
+  if (!have_repo_arg && am_root)
+    repo = "/sysroot/ostree/repo";
+  else if (have_repo_arg)
+    repo = argv[1] + strlen ("--repo=");
+  else
+    repo = NULL;
+
+  cmd = strchr (argv[0], '-');
+  if (cmd)
+    {
+      cmd += 1;
+      arg_off = 1;
+      if (have_repo_arg)
+        arg_off += 1;
+    }
+  else if (!have_repo_arg)
+    {
+      arg_off = 2;
+      cmd = argv[arg_off-1];
+    }
+  else
+    {
+      arg_off = 3;
+      cmd = argv[arg_off-1];
+    }
+
+  builtin = builtins;
+  while (builtin->name)
+    {
+      if (strcmp (cmd, builtin->name) == 0)
+        break;
+      builtin++;
+    }
+
+  if (!builtin->name)
+    {
+      set_error_print_usage (&error, builtins, "Unknown command", argv);
+      goto out;
+    }
+
+  if (repo == NULL && !(builtin->flags & OSTREE_BUILTIN_FLAG_NO_REPO))
+    {
+      set_error_print_usage (&error, builtins, "Command requires a --repo argument", argv);
+      goto out;
+    }
+  
+  prep_builtin_argv (cmd, argc-arg_off, argv+arg_off, &cmd_argc, &cmd_argv);
+
+  if (!builtin->fn (cmd_argc, cmd_argv, repo, &error))
+    goto out;
+
+ out:
+  g_free (cmd_argv);
+  if (error)
+    {
+      g_printerr ("%s\n", error->message);
+      g_clear_error (&error);
+      return 1;
+    }
+  return 0;
+}
diff --git a/src/ostree/ot-main.h b/src/ostree/ot-main.h
new file mode 100644 (file)
index 0000000..2fb54cd
--- /dev/null
@@ -0,0 +1,37 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2011 Colin Walters <walters@verbum.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Colin Walters <walters@verbum.org>
+ */
+
+#include <gio/gio.h>
+
+typedef enum {
+  OSTREE_BUILTIN_FLAG_NONE = 0,
+  OSTREE_BUILTIN_FLAG_NO_REPO = 1,
+} OstreeBuiltinFlags;
+
+typedef struct {
+  const char *name;
+  gboolean (*fn) (int argc, char **argv, const char *repo, GError **error);
+  int flags; /* OstreeBuiltinFlags */
+} OstreeBuiltin;
+
+int ostree_main (int    argc, char **argv, OstreeBuiltin  *builtins);
+
index 6bc7ff69b2a20c55af3a83f94bb85890674ea675..53c85b22c105b3a33eb896f0031c63a3fdb7f490 100755 (executable)
@@ -26,9 +26,9 @@ echo '1..2'
 setup_fake_remote_repo1
 cd ${test_tmpdir}
 mkdir repo
-$OSTREE init
-$OSTREE remote add origin $(cat httpd-address)/ostree/gnomerepo
-$OSTREE pull origin main
+ostree --repo=repo init
+ostree --repo=repo remote add origin $(cat httpd-address)/ostree/gnomerepo
+ostree-pull --repo=repo origin main
 echo "ok pull"
 
 cd ${test_tmpdir}